#include <bsl_err.h>
#include <bsl_sal.h>
#include <crypt_algid.h>
#include <crypt_eal_cipher.h>
#include <crypt_eal_provider.h>
#include <crypt_errno.h>
#include <crypt_sm4.h>

#include <securec.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include <cmocka.h>

#include "helper.h"
#include <kaep_err.h>

#define GROUP_TEST_MAX 200
#define MAXSIZE        1024

#define BLOCKSIZE 16
#define KEYSIZE   32

typedef struct {
    int32_t id;
    char *keyHex;
    char *ivHex;
    int32_t temp;
    int32_t padding;
    int isSetPadding;
    char *inHex;
    char *outHex;
} CRYPT_EAL_Hex;

static int32_t KAE_SM4_ALG_ID[] = {
    CRYPT_CIPHER_SM4_ECB, CRYPT_CIPHER_SM4_CBC, CRYPT_CIPHER_SM4_OFB, CRYPT_CIPHER_SM4_XTS, CRYPT_CIPHER_SM4_CTR,
};

static int32_t KAE_SM4_UNSUPPORT_ID[] = {
    CRYPT_CIPHER_SM4_GCM,
    CRYPT_CIPHER_SM4_CFB,
};

static CRYPT_EAL_Hex SDV_KAE_SM4_INIT_API_TC001_HEX[] = {
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_INIT_API_TC002_HEX[] = {
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "ffffffffffffffffffffffffffffffff", 1, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "ffffffffffffffffffffffffffffffff", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "00000000000000000000000000000000", 1, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "00000000000000000000000000000000", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 1, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 0, 0, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_INIT_API_TC003_HEX[] = {
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_REINIT_API_TC001_HEX[] = {
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_UPDATE_API_TC001_HEX[] = {
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 1, 0, 0, "6BC1BEE22E409F96E93D7E117393172A", NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 0, 0, 0, "E9538251C71D7B80BBE4483FEF497BD1", NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1, 0, 0,
     "6BC1BEE22E409F96E93D7E117393172A", NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0,
     "AC529AF989A62FCE9CDDC5FFB84125CA", NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1, 0, 0,
     "6BC1BEE22E409F96E93D7E117393172A", NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0,
     "14AE4A72B97A93CE1216CCD998E371C1", NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1, 0, 0,
     "6BC1BEE22E409F96E93D7E117393172A", NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0,
     "BC710D762D070B26361DA82B54565E46", NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_CTRL_API_TC001_HEX[] = {
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0,
     "6BC1BEE22E409F96E93D7E117393172A", NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0,
     "6BC1BEE22E409F96E93D7E117393172A", NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_CTRL_API_TC002_HEX[] = {
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_FUNC_TC001_HEX[] = {
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_PKCS7, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_PKCS7, 1, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_PKCS5, 1, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_X923, 1, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_ISO7816, 1, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_ZEROS, 1, NULL, NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_NONE, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_NONE, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_FUNC_TC002_HEX[] = {
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1,
     CRYPT_PADDING_PKCS7, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 10,
     CRYPT_PADDING_PKCS7, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 15,
     CRYPT_PADDING_PKCS7, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1000,
     CRYPT_PADDING_PKCS7, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1,
     CRYPT_PADDING_PKCS5, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 10,
     CRYPT_PADDING_PKCS5, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 15,
     CRYPT_PADDING_PKCS5, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 33,
     CRYPT_PADDING_PKCS5, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1,
     CRYPT_PADDING_X923, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 10,
     CRYPT_PADDING_X923, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 15,
     CRYPT_PADDING_X923, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 33,
     CRYPT_PADDING_X923, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1,
     CRYPT_PADDING_ISO7816, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 10,
     CRYPT_PADDING_ISO7816, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 15,
     CRYPT_PADDING_ISO7816, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 33,
     CRYPT_PADDING_ISO7816, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 1,
     CRYPT_PADDING_ZEROS, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 10,
     CRYPT_PADDING_ZEROS, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 15,
     CRYPT_PADDING_ZEROS, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 33,
     CRYPT_PADDING_ZEROS, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 128,
     CRYPT_PADDING_NONE, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 16,
     CRYPT_PADDING_NONE, 0, NULL, NULL},
};

static CRYPT_EAL_Hex SDV_KAE_SM4_FUNC_TC003_HEX[] = {
    {
        CRYPT_CIPHER_SM4_ECB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "",
        0,
        CRYPT_PADDING_PKCS7,
        0,
        "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
        "a51411ff04a711443891fce7ab842a29d5b50f46a9a730a0f590ffa776d99855c9a86a4d71447f4e873ada4f388af9b92b25557b50514d155939e6ec940ad90e",
    },
    {
        CRYPT_CIPHER_SM4_ECB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        0,
        CRYPT_PADDING_PKCS7,
        0,
        "bc710d762d070b26361da82b54565e46",
        "0ae0c82f7439fe0f3d71a46d665f3d05",
    },
    {
        CRYPT_CIPHER_SM4_CTR,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        0,
        CRYPT_PADDING_PKCS7,
        0,
        "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
        "14AE4A72B97A93CE1216CCD998E371C160F7EF8B6344BD6DA1992505E5FC219B0BF057F86C5D75103C0F46519C7FB2E7292805035ADB9A90ECEF145359D7CF0E",
    },
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_PKCS7, 0,
     "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
     "AC529AF989A62FCE9CDDC5FFB84125CAB168DD69DB3C0EEA1AB16DE6AEA43C592C15567BFF8F707486C202C7BE59101F74A629B350CD7E11BE99998AF5206D6C"},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0,
     CRYPT_PADDING_PKCS7, 0,
     "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
     "BC710D762D070B26361DA82B54565E4607A0C62834740AD3240D239125E11621D476B21CC9F04951F0741D2EF9E094981584FC142BF13AA626B82F9D7D076CCE"},
    {
        CRYPT_CIPHER_SM4_XTS,
        "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        0,
        CRYPT_PADDING_PKCS7,
        0,
        "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17",
        "E9538251C71D7B80BBE4483FEF497BD12C5C581BD6242FC51E08964FB4F60FDB0BA42F63499279213D318D2C11F6886E903BE7F93A1B3479",
    },
    {
        CRYPT_CIPHER_SM4_XTS,
        "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        0,
        CRYPT_PADDING_PKCS7,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        "E9538251C71D7B80BBE4483FEF497BD1",
    },
};

static CRYPT_EAL_Hex SDV_KAE_SM4_MULTI_UPDATE_TC001_HEX[] = {
    {
        CRYPT_CIPHER_SM4_CBC,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        8,
        CRYPT_PADDING_PKCS7,
        1,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_CBC,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        8,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411E5FBC1191A0A52EFF69F2445DF4F9B17AD2B417BE66C3710",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_OFB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        8,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_OFB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        3,
        CRYPT_PADDING_PKCS7,
        1,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_CTR,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        3,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_OFB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        3,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_CBC,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        16,
        CRYPT_PADDING_PKCS7,
        1,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_CTR,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        16,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_OFB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        16,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
};

static CRYPT_EAL_Hex SDV_KAE_SM4_MULTI_UPDATE_TC002_HEX[] = {
    {
        CRYPT_CIPHER_SM4_CBC,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        0,
        CRYPT_PADDING_PKCS7,
        1,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_CTR,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
        0,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
    {
        CRYPT_CIPHER_SM4_OFB,
        "2b7e151628aed2a6abf7158809cf4f3c",
        "000102030405060708090A0B0C0D0E0F",
        0,
        CRYPT_PADDING_NONE,
        0,
        "6BC1BEE22E409F96E93D7E117393172A",
        NULL,
    },
};

static CRYPT_EAL_Hex SDV_KAE_SM4_CTRL_API_TC003_HEX[] = {
    {CRYPT_CIPHER_SM4_CBC, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_CTR, "2b7e151628aed2a6abf7158809cf4f3c", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_OFB, "2b7e151628aed2a6abf7158809cf4f3c", "000102030405060708090A0B0C0D0E0F", 0, 0, 0, NULL, NULL},
    {CRYPT_CIPHER_SM4_XTS, "2b7e151628aed2a6abf7158809cf4f3c000102030405060708090a0b0c0d0e0f",
     "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", 0, 0, 0, NULL, NULL},
};

static int SetPadding(int isSetPadding, CRYPT_EAL_CipherCtx *ctxEnc, int padding)
{
    if (isSetPadding == 1) {
        return CRYPT_EAL_CipherSetPadding(ctxEnc, padding);
    }
    return CRYPT_SUCCESS;
}

static CRYPT_EAL_LibCtx *CreateLoadLibCtx()
{
    CRYPT_EAL_LibCtx *libctx = CRYPT_EAL_LibCtxNew();
    assert_non_null(libctx);
    assert_int_equal(CRYPT_EAL_ProviderSetLoadPath(libctx, "../../build"), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_ProviderLoad(libctx, BSL_SAL_LIB_FMT_LIBSO, "kae_provider", NULL, NULL), CRYPT_SUCCESS);
    return libctx;
}

static void SDV_KAE_SM4_PROVIDER_LOAD(void **state)
{
    (void)state;
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_NEW_API_TC001(void **state)
{
    int32_t *id = *state;
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, *id, "provider=kaev1");
    assert_non_null(ctx);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_NEW_API_TC002(void **state)
{
    int32_t *id = *state;
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, *id, "provider=kaev1");
    assert_null(ctx);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_INIT_API_TC001(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, NULL, 0, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, 0, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, BLOCKSIZE - 1, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, BLOCKSIZE + 1, true), CRYPT_SUCCESS);

    FreeHex(key);
    FreeHex(iv);

    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_INIT_API_TC002(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, CRYPT_CIPHER_SM4_XTS, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherInit(NULL, key->x, key->len, iv->x, iv->len, hex->temp), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, NULL, key->len, iv->x, iv->len, hex->temp), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, NULL, iv->len, hex->temp), CRYPT_NULL_INPUT);

    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, 0, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, 1, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, 16, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, 33, iv->x, iv->len, true), CRYPT_SUCCESS);

    uint8_t unsafe_key[KEYSIZE] = {0};
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, unsafe_key, KEYSIZE, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, unsafe_key, KEYSIZE, iv->x, iv->len, false), CRYPT_SUCCESS);

    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, 0, hex->temp), CRYPT_MODES_IVLEN_ERROR);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, 1, hex->temp), CRYPT_MODES_IVLEN_ERROR);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, 15, hex->temp), CRYPT_MODES_IVLEN_ERROR);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, 17, hex->temp), CRYPT_MODES_IVLEN_ERROR);

    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, hex->temp), CRYPT_SUCCESS);

    FreeHex(key);
    FreeHex(iv);

    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_INIT_API_TC003(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherInit(NULL, key->x, key->len, iv->x, iv->len, true), CRYPT_NULL_INPUT);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, NULL, 0, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, 0, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, BLOCKSIZE - 1, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, BLOCKSIZE + 1, iv->x, iv->len, true), CRYPT_SUCCESS);

    FreeHex(key);
    FreeHex(iv);

    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_CRYPTO_SM4_DEINIT_API_TC001(void **state)
{
    int32_t *id = *state;
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, *id, "provider=kaev1");
    assert_non_null(ctx);

    CRYPT_EAL_CipherDeinit(ctx);
    CRYPT_EAL_CipherDeinit(NULL);

    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_REINIT_API_TC001(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherReinit(ctx, iv->x, iv->len), CRYPT_EAL_ERR_STATE);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherReinit(NULL, iv->x, iv->len), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_CipherReinit(ctx, NULL, iv->len), CRYPT_NULL_INPUT);
    assert_int_equal(CRYPT_EAL_CipherReinit(ctx, iv->x, 0), CRYPT_MODES_IVLEN_ERROR);

    FreeHex(key);
    FreeHex(iv);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_UPDATE_API_TC001(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();
    Hex *in = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);
    assert_int_equal(ConvertHex(hex->inHex, in), 0);

    uint8_t out[BLOCKSIZE] = {0};
    uint32_t len = BLOCKSIZE;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, hex->temp), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(NULL, in->x, in->len, out, &len), CRYPT_NULL_INPUT);
    len = BLOCKSIZE;
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, NULL, in->len, out, &len), CRYPT_NULL_INPUT);
    len = BLOCKSIZE;
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, in->len, NULL, &len), CRYPT_NULL_INPUT);
    len = BLOCKSIZE;
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, 0, NULL, &len), CRYPT_NULL_INPUT);
    len = BLOCKSIZE;
    if (hex->id == CRYPT_CIPHER_SM4_XTS) {
        assert_int_not_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, 1, out, &len), CRYPT_SUCCESS);
    } else {
        assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, 1, out, &len), CRYPT_SUCCESS);
    }
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, in->len, out, NULL), CRYPT_NULL_INPUT);
    len = BLOCKSIZE;
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, in->len, out, &len), CRYPT_SUCCESS);
    assert_int_equal(len, BLOCKSIZE);

    FreeHex(key);
    FreeHex(iv);
    FreeHex(in);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_CTRL_API_TC001(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();
    Hex *in = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);
    assert_int_equal(ConvertHex(hex->inHex, in), 0);

    uint8_t iv1[BLOCKSIZE] = {0};
    uint8_t iv2[BLOCKSIZE] = {0};
    const uint32_t len = BLOCKSIZE;
    uint8_t out[MAXSIZE] = {0};
    uint32_t outlen = MAXSIZE;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_AAD, iv->x, iv->len), CRYPT_MODES_CTRL_TYPE_ERROR);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_IV, iv1, len), CRYPT_SUCCESS);
    assert_memory_equal(iv1, iv->x, iv->len);
    (void)memset_s(iv1, BLOCKSIZE, 0, BLOCKSIZE);

    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, BLOCKSIZE - 1, out, &outlen), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_IV, iv1, len), CRYPT_SUCCESS);
    assert_memory_equal(iv1, iv->x, iv->len);

    outlen = MAXSIZE;
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, in->x, 1, out, &outlen), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_IV, iv2, len), CRYPT_SUCCESS);
    assert_memory_not_equal(iv1, iv2, BLOCKSIZE);

    FreeHex(key);
    FreeHex(iv);
    FreeHex(in);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_CTRL_API_TC002(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    uint8_t iv1[BLOCKSIZE] = {0};
    const uint32_t len = BLOCKSIZE;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_SET_AAD, iv->x, iv->len), CRYPT_MODES_CTRL_TYPE_ERROR);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_IV, iv1, len), CRYPT_SUCCESS);

    FreeHex(key);
    FreeHex(iv);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_FUNC_TC001(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    uint8_t outTmp[MAXSIZE] = {0};
    uint8_t result[MAXSIZE] = {0};
    uint32_t totalLen = 0;
    uint32_t decLen = MAXSIZE;
    uint32_t len = MAXSIZE;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctxEnc = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxEnc);
    assert_int_equal(SetPadding(hex->isSetPadding, ctxEnc, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxEnc, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxEnc, outTmp, &len), CRYPT_SUCCESS);

    CRYPT_EAL_CipherCtx *ctxDec = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxDec);

    assert_int_equal(SetPadding(hex->isSetPadding, ctxDec, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxDec, key->x, key->len, iv->x, iv->len, false), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctxDec, outTmp, len, result, &decLen), CRYPT_SUCCESS);
    totalLen += decLen;
    decLen = MAXSIZE - totalLen;
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxDec, result + totalLen, &decLen), CRYPT_SUCCESS);

    FreeHex(key);
    FreeHex(iv);

    CRYPT_EAL_CipherFreeCtx(ctxEnc);
    CRYPT_EAL_CipherFreeCtx(ctxDec);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_FUNC_TC002(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    uint8_t input[MAXSIZE] = {0};
    uint8_t outTmp[MAXSIZE] = {0};
    uint8_t result[MAXSIZE] = {0};
    uint32_t totalLen = 0;
    uint32_t leftLen = MAXSIZE;
    uint32_t len = MAXSIZE;

    (void)memset_s(outTmp, MAXSIZE, 0xAA, MAXSIZE);
    (void)memset_s(input, MAXSIZE, 0xAA, MAXSIZE);

    int32_t inLen = hex->temp;
    assert_true(inLen <= MAXSIZE);
    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctxEnc = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxEnc);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxEnc, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherSetPadding(ctxEnc, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctxEnc, input, inLen, outTmp, &len), CRYPT_SUCCESS);
    totalLen += len;
    leftLen -= len;
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxEnc, outTmp + totalLen, &leftLen), CRYPT_SUCCESS);
    totalLen += leftLen;
    len = MAXSIZE;
    leftLen = MAXSIZE;
    CRYPT_EAL_CipherCtx *ctxDec = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxDec);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxDec, key->x, key->len, iv->x, iv->len, false), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherSetPadding(ctxDec, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctxDec, outTmp, totalLen, result, &len), CRYPT_SUCCESS);
    leftLen -= len;
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxDec, result + len, &leftLen), CRYPT_SUCCESS);
    assert_memory_equal(input, result, inLen);

    FreeHex(key);
    FreeHex(iv);
    CRYPT_EAL_CipherFreeCtx(ctxEnc);
    CRYPT_EAL_CipherFreeCtx(ctxDec);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_FUNC_TC003(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();
    Hex *plainText = NewHex();
    Hex *cipherText = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);
    assert_int_equal(ConvertHex(hex->inHex, plainText), 0);
    assert_int_equal(ConvertHex(hex->outHex, cipherText), 0);

    uint8_t out[MAXSIZE] = {0};
    uint32_t len = plainText->len;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, plainText->x, plainText->len, out, &len), CRYPT_SUCCESS);
    assert_memory_equal(out, cipherText->x, len);

    FreeHex(key);
    FreeHex(iv);
    FreeHex(plainText);
    FreeHex(cipherText);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_FUNC_TC004(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();
    Hex *plainText = NewHex();
    Hex *cipherText = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);
    assert_int_equal(ConvertHex(hex->inHex, plainText), 0);
    assert_int_equal(ConvertHex(hex->outHex, cipherText), 0);

    uint8_t out[MAXSIZE] = {0};
    uint32_t len = cipherText->len;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);
    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, false), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctx, cipherText->x, cipherText->len, out, &len), CRYPT_SUCCESS);
    assert_memory_equal(out, plainText->x, len);

    FreeHex(key);
    FreeHex(iv);
    FreeHex(plainText);
    FreeHex(cipherText);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_MULTI_UPDATE_TC001(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();
    Hex *in = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);
    assert_int_equal(ConvertHex(hex->inHex, in), 0);

    uint8_t outTmp[MAXSIZE * 4] = {0};
    uint8_t result[MAXSIZE * 4] = {0};
    uint32_t totalLen = 0;
    uint32_t leftLen = MAXSIZE * 4;
    uint32_t len = MAXSIZE * 4;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctxEnc = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxEnc);
    assert_int_equal(SetPadding(hex->isSetPadding, ctxEnc, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxEnc, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    for (int i = 0; i < hex->temp; i++) {
        assert_int_equal(CRYPT_EAL_CipherUpdate(ctxEnc, in->x, in->len, outTmp + totalLen, &len), CRYPT_SUCCESS);
        totalLen += len;
        leftLen -= len;
        len = leftLen;
    }
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxEnc, outTmp + totalLen, &leftLen), CRYPT_SUCCESS);
    totalLen += leftLen;

    len = MAXSIZE * 4;
    leftLen = MAXSIZE * 4;
    CRYPT_EAL_CipherCtx *ctxDec = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxDec);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxDec, key->x, key->len, iv->x, iv->len, false), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherSetPadding(ctxDec, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctxDec, outTmp, totalLen, result, &len), CRYPT_SUCCESS);
    leftLen -= len;
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxDec, result + len, &leftLen), CRYPT_SUCCESS);

    assert_memory_equal(in->x, result, in->len);
    assert_memory_equal(in->x, result + in->len, in->len);

    FreeHex(key);
    FreeHex(iv);
    FreeHex(in);
    CRYPT_EAL_CipherFreeCtx(ctxEnc);
    CRYPT_EAL_CipherFreeCtx(ctxDec);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_MULTI_UPDATE_TC002(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();
    Hex *in = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);
    assert_int_equal(ConvertHex(hex->inHex, in), 0);

    uint8_t outTmp[MAXSIZE * 4] = {0};
    uint8_t result[MAXSIZE * 4] = {0};
    uint32_t totalLen = 0;
    uint32_t leftLen = MAXSIZE * 4;
    uint32_t len = MAXSIZE * 4;

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctxEnc = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxEnc);
    assert_int_equal(SetPadding(hex->isSetPadding, ctxEnc, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxEnc, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    for (int i = 0; i < 2; i++) {
        assert_int_equal(CRYPT_EAL_CipherUpdate(ctxEnc, in->x, BLOCKSIZE - 1, outTmp + totalLen, &len), CRYPT_SUCCESS);
        totalLen += len;
        leftLen -= len;
        len = leftLen;
        assert_int_equal(CRYPT_EAL_CipherUpdate(ctxEnc, in->x, BLOCKSIZE, outTmp + totalLen, &len), CRYPT_SUCCESS);
        totalLen += len;
        leftLen -= len;
        len = leftLen;
    }
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctxEnc, in->x, BLOCKSIZE - 1, outTmp + totalLen, &len), CRYPT_SUCCESS);
    totalLen += len;
    leftLen -= len;
    len = leftLen;
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxEnc, outTmp + totalLen, &leftLen), CRYPT_SUCCESS);
    totalLen += leftLen;

    len = MAXSIZE * 4;
    leftLen = MAXSIZE * 4;
    CRYPT_EAL_CipherCtx *ctxDec = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctxDec);
    assert_int_equal(CRYPT_EAL_CipherInit(ctxDec, key->x, key->len, iv->x, iv->len, false), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherSetPadding(ctxDec, hex->padding), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherUpdate(ctxDec, outTmp, totalLen, result, &len), CRYPT_SUCCESS);
    leftLen -= len;
    assert_int_equal(CRYPT_EAL_CipherFinal(ctxDec, result + len, &leftLen), CRYPT_SUCCESS);

    assert_memory_equal(in->x, result, BLOCKSIZE - 1);
    assert_memory_equal(in->x, result + BLOCKSIZE - 1, BLOCKSIZE);

    FreeHex(key);
    FreeHex(iv);
    FreeHex(in);
    CRYPT_EAL_CipherFreeCtx(ctxEnc);
    CRYPT_EAL_CipherFreeCtx(ctxDec);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_CTRL_API_TC003(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    uint8_t niv[BLOCKSIZE] = {0};

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, iv->x, iv->len, true), CRYPT_SUCCESS);
    assert_int_equal(CRYPT_EAL_CipherCtrl(ctx, CRYPT_CTRL_GET_IV, niv, iv->len), CRYPT_SUCCESS);
    assert_memory_equal(niv, iv->x, iv->len);

    FreeHex(key);
    FreeHex(iv);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

static void SDV_KAE_SM4_REINIT_API_TC002(void **state)
{
    CRYPT_EAL_Hex *hex = (CRYPT_EAL_Hex *)*state;

    Hex *key = NewHex();
    Hex *iv = NewHex();

    assert_int_equal(ConvertHex(hex->keyHex, key), 0);
    assert_int_equal(ConvertHex(hex->ivHex, iv), 0);

    CRYPT_EAL_LibCtx *libctx = CreateLoadLibCtx();
    CRYPT_EAL_CipherCtx *ctx = CRYPT_EAL_ProviderCipherNewCtx(libctx, hex->id, "provider=kaev1");
    assert_non_null(ctx);

    assert_int_not_equal(CRYPT_EAL_CipherInit(ctx, key->x, key->len, NULL, 0, true), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherReinit(ctx, NULL, 0), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherReinit(ctx, iv->x, 0), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherReinit(ctx, iv->x, BLOCKSIZE - 1), CRYPT_SUCCESS);
    assert_int_not_equal(CRYPT_EAL_CipherReinit(ctx, iv->x, BLOCKSIZE + 1), CRYPT_SUCCESS);

    FreeHex(key);
    FreeHex(iv);
    CRYPT_EAL_CipherFreeCtx(ctx);
    CRYPT_EAL_LibCtxFree(libctx);
}

int main(void)
{
    struct CMUnitTest tests[GROUP_TEST_MAX] = {NULL};
    int testCnt = 0;
    tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test(SDV_KAE_SM4_PROVIDER_LOAD);
    for (size_t i = 0; i < sizeof(KAE_SM4_ALG_ID) / sizeof(KAE_SM4_ALG_ID[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_NEW_API_TC001, &KAE_SM4_ALG_ID[i]);
    }
    for (size_t i = 0; i < sizeof(KAE_SM4_UNSUPPORT_ID) / sizeof(KAE_SM4_UNSUPPORT_ID[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_NEW_API_TC002, &KAE_SM4_UNSUPPORT_ID[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_INIT_API_TC001_HEX) / sizeof(SDV_KAE_SM4_INIT_API_TC001_HEX[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_INIT_API_TC001,
                                                                        &SDV_KAE_SM4_INIT_API_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_INIT_API_TC002_HEX) / sizeof(SDV_KAE_SM4_INIT_API_TC002_HEX[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_INIT_API_TC002,
                                                                        &SDV_KAE_SM4_INIT_API_TC002_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_INIT_API_TC003_HEX) / sizeof(SDV_KAE_SM4_INIT_API_TC003_HEX[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_INIT_API_TC003,
                                                                        &SDV_KAE_SM4_INIT_API_TC003_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(KAE_SM4_ALG_ID) / sizeof(KAE_SM4_ALG_ID[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_CRYPTO_SM4_DEINIT_API_TC001, &KAE_SM4_ALG_ID[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_REINIT_API_TC001_HEX) / sizeof(SDV_KAE_SM4_REINIT_API_TC001_HEX[0]);
         i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_REINIT_API_TC001,
                                                                        &SDV_KAE_SM4_REINIT_API_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_UPDATE_API_TC001_HEX) / sizeof(SDV_KAE_SM4_UPDATE_API_TC001_HEX[0]);
         i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_UPDATE_API_TC001,
                                                                        &SDV_KAE_SM4_UPDATE_API_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_CTRL_API_TC001_HEX) / sizeof(SDV_KAE_SM4_CTRL_API_TC001_HEX[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_CTRL_API_TC001,
                                                                        &SDV_KAE_SM4_CTRL_API_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_CTRL_API_TC002_HEX) / sizeof(SDV_KAE_SM4_CTRL_API_TC002_HEX[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_CTRL_API_TC002,
                                                                        &SDV_KAE_SM4_CTRL_API_TC002_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_FUNC_TC001_HEX) / sizeof(SDV_KAE_SM4_FUNC_TC001_HEX[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_FUNC_TC001, &SDV_KAE_SM4_FUNC_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_FUNC_TC002_HEX) / sizeof(SDV_KAE_SM4_FUNC_TC002_HEX[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_FUNC_TC002, &SDV_KAE_SM4_FUNC_TC002_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_FUNC_TC003_HEX) / sizeof(SDV_KAE_SM4_FUNC_TC003_HEX[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_FUNC_TC003, &SDV_KAE_SM4_FUNC_TC003_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_FUNC_TC003_HEX) / sizeof(SDV_KAE_SM4_FUNC_TC003_HEX[0]); i++) {
        tests[testCnt++] =
            (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_FUNC_TC004, &SDV_KAE_SM4_FUNC_TC003_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_MULTI_UPDATE_TC001_HEX) / sizeof(SDV_KAE_SM4_MULTI_UPDATE_TC001_HEX[0]);
         i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_MULTI_UPDATE_TC001,
                                                                        &SDV_KAE_SM4_MULTI_UPDATE_TC001_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_MULTI_UPDATE_TC002_HEX) / sizeof(SDV_KAE_SM4_MULTI_UPDATE_TC002_HEX[0]);
         i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_MULTI_UPDATE_TC002,
                                                                        &SDV_KAE_SM4_MULTI_UPDATE_TC002_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_CTRL_API_TC003_HEX) / sizeof(SDV_KAE_SM4_CTRL_API_TC003_HEX[0]); i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_CTRL_API_TC003,
                                                                        &SDV_KAE_SM4_CTRL_API_TC003_HEX[i]);
    }
    for (size_t i = 0; i < sizeof(SDV_KAE_SM4_REINIT_API_TC001_HEX) / sizeof(SDV_KAE_SM4_REINIT_API_TC001_HEX[0]);
         i++) {
        tests[testCnt++] = (struct CMUnitTest)cmocka_unit_test_prestate(SDV_KAE_SM4_REINIT_API_TC002,
                                                                        &SDV_KAE_SM4_REINIT_API_TC001_HEX[i]);
    }

    cmocka_run_group_tests(tests, NULL, NULL);
    return 0;
}